package com.neuedu.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.neuedu.common.Result;
import com.neuedu.dto.GoodsDto;
import com.neuedu.pojo.Category;
import com.neuedu.pojo.Goods;
import com.neuedu.pojo.GoodsSpec;
import com.neuedu.pojo.ShoppingCart;
import com.neuedu.service.CategoryService;
import com.neuedu.service.GoodsService;
import com.neuedu.service.GoodsSpecService;
import com.neuedu.service.ShoppingCartService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.stream.Collectors;


@Slf4j
@RestController
@RequestMapping("/goods")
public class GoodsController {

    @Autowired
    private GoodsService goodsService;
    @Autowired
    private GoodsSpecService goodsSpecService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    ShoppingCartService shoppingCartService;


    /**
     * 添加商品
     *
     * @param goods
     * @return
     */
    @PostMapping
    public Result<String> saveGoods(@RequestBody Goods goods) {
        if (goods.getSort() == null) {
            goods.setSort(0);
        }
        goods.setStatus(true);
        //插入商品
        boolean isSaved = goodsService.save(goods);
        if (!isSaved) {
            return Result.error("增加商品时失败");
        }
        return Result.success("成功添加商品");
    }


    /**
     * 修改商品
     *
     * @param goods
     * @return
     */
    @PutMapping
    public Result<String> updateGoods(@RequestBody Goods goods) {

        log.info(goods.toString());
        boolean isUpdated = goodsService.updateById(goods);
        if (isUpdated)
            return Result.success("成功修改商品信息");
        else
            return Result.error("修改商品信息失败");
    }

    /**
     * 查询商品详情
     *
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    @Transactional
    public Result<GoodsDto> getById(@PathVariable Long id) {
        Goods goods = goodsService.getById(id);
        Category category = categoryService.getById(goods.getCategoryId());
        GoodsDto goodsDto = new GoodsDto();
        BeanUtils.copyProperties(goods, goodsDto);
        goodsDto.setCategoryName(category.getName());

        // 查询商品SKU
        LambdaQueryWrapper<GoodsSpec> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(GoodsSpec::getGoodsId, id);
        List<GoodsSpec> goodsSpecs = goodsSpecService.list(queryWrapper);
        goodsDto.setGoodsSpecs(goodsSpecs);

        return Result.success(goodsDto);
    }

    /**
     * 商品信息分页查询
     *
     * @param page
     * @param pageSize
     * @param query
     * @return
     */
    @GetMapping("/page")
    public Result<Page<GoodsDto>> page(int page, int pageSize, String query) {
        log.info("page={}, pageSize={}, username={}", page, pageSize, query);
        //构造分页构造器
        Page<Goods> pageInfo = new Page<Goods>(page, pageSize);
        Page<GoodsDto> goodsDtoPage = new Page<>();
        //构造条件构造器
        LambdaQueryWrapper<Goods> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.like(null != query, Goods::getName, query);
        queryWrapper.orderByDesc(Goods::getSort);
        goodsService.page(pageInfo, queryWrapper);

        BeanUtils.copyProperties(pageInfo, goodsDtoPage, "records");
        List<GoodsDto> goodsDtos = convertGoodsDto(pageInfo.getRecords());
        goodsDtoPage.setRecords(goodsDtos);
        return Result.success(goodsDtoPage);
    }

    /**
     * 获取商品列表
     * @param query
     * @return
     */
    @GetMapping("/list")
    public Result<List<GoodsDto>> page(String query, Long categoryId) {
        LambdaQueryWrapper<Goods> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.like(null != query, Goods::getName, query);
        queryWrapper.eq(null != categoryId, Goods::getCategoryId, categoryId);
        queryWrapper.orderByDesc(Goods::getSort);

        List<Goods> goods = goodsService.list(queryWrapper);

        List<GoodsDto> goodsDtos = convertGoodsDto(goods);
        return Result.success(goodsDtos);
    }

    /**
     * 删除商品及对应所有规格
     *
     * @param id
     * @return
     */
    @DeleteMapping("/{id}")
    @Transactional
    public Result<String> deleteById(@PathVariable Long id) {
        //删除商品
        boolean isGoodsDeleted = goodsService.removeById(id);
        if (!isGoodsDeleted) {
            return Result.error("删除商品时失败");
        }
        // 删除购物车中的商品
        LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShoppingCart::getGoodsId, id);
        shoppingCartService.remove(queryWrapper);

        //删除商品的所有规格
        LambdaQueryWrapper<GoodsSpec> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(GoodsSpec::getGoodsId, id);
        boolean isSpecDeleted = goodsSpecService.remove(lambdaQueryWrapper);
        if (isSpecDeleted) {
            return Result.error("删除商品规格时失败");
        }
        return Result.success("成功删除商品及其所有规格");
    }


    /**
     * 删除商品某个规格
     *
     * @param id
     * @return
     */
    @DeleteMapping("/spec/{id}")
    @Transactional
    public Result<String> deleteSpecById(@PathVariable Long id) {

        boolean isSpecDeleted = goodsSpecService.removeById(id);
        // 删除某个规格时，删除购物车中的数据
        LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShoppingCart::getSpecId, id);
        shoppingCartService.remove(queryWrapper);

        if (!isSpecDeleted) {
            return Result.error("删除商品规格时失败");
        } else {
            return Result.success("成功删除该种商品规格");
        }
    }

    /**
     * 增加商品的规格
     *
     * @param goodsSpec
     * @return
     */
    @PostMapping("/spec")
    public Result<String> addSpec(@RequestBody GoodsSpec goodsSpec) {
        // 查询当前商品下是否有此规格，如果存在，则返回规格已存在
        LambdaQueryWrapper<GoodsSpec> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(GoodsSpec::getGoodsId, goodsSpec.getGoodsId());
        List<GoodsSpec> goodsSpecs = goodsSpecService.list(queryWrapper);
        for (GoodsSpec spec : goodsSpecs) {
            if(spec.getSpecValue().equals(goodsSpec.getSpecValue())){
                return Result.error(goodsSpec.getSpecValue()+"规格已存在");
            }
        }

        boolean isSaved = goodsSpecService.save(goodsSpec);
        if (isSaved)
            return Result.success("成功为该商品添加了此规格");
        else
            return Result.success("为该商品添加规格失败");

    }


    /**
     * 修改某个商品规格
     *
     * @param goodsSpec
     * @return
     */
    @PutMapping("/spec")
    public Result<String> changeSpec(@RequestBody GoodsSpec goodsSpec) {

        boolean isUpdated = goodsSpecService.updateById(goodsSpec);
        if (isUpdated)
            return Result.success("成功修改商品规格信息");
        else
            return Result.error("修改商品规格信息失败");
    }

    /**
     * 根据id查询sku信息
     *
     * @param id
     * @return
     */
    @GetMapping("/spec/{id}")
    public Result<GoodsSpec> getSpecById(@PathVariable Long id) {

        GoodsSpec goodsSpec = goodsSpecService.getById(id);
        if (goodsSpec != null) {
            return Result.success(goodsSpec);
        } else {
            return Result.error("查询商品规格信息失败");
        }
    }

    /**
     * 推荐商品
     *
     * @return
     */
    @GetMapping("/recommend")
    public Result<List<Goods>> getRecommend() {

        // 总记录数
        int count = goodsService.count();
        // 随机数起始位置
        int randomCount = (int) (Math.random() * count);

        LambdaQueryWrapper<Goods> wrapper = new LambdaQueryWrapper();
        wrapper.orderByDesc(Goods::getId);
        wrapper.last("limit " + String.valueOf(randomCount) + ", 10");
        List<Goods> randomList = goodsService.list(wrapper);

        return Result.success(randomList);
    }


    /**
     * 关键词搜索商品
     * 未实现权重搜索
     *
     * @param keyword
     * @return
     */
    @GetMapping("/search")
    public Result<List<Goods>> search(@RequestParam String keyword) {
        String[] list = keyword.split("");

        LambdaQueryWrapper<Goods> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.like(Goods::getName, keyword);

        for (int i = 0; i < list.length; i++) {
            lambdaQueryWrapper.or().like(Goods::getName, list[i]);
        }

        List<Goods> rlt = goodsService.list(lambdaQueryWrapper);
        return Result.success(rlt);
    }

    public List<GoodsDto> convertGoodsDto(List<Goods> goods){
        List<GoodsDto> goodsDtos = goods.stream().map((item) -> {
            GoodsDto goodsDto = new GoodsDto();
            BeanUtils.copyProperties(item, goodsDto);
            Category category = categoryService.getById(item.getCategoryId());
            goodsDto.setCategoryName(category.getName());
            return goodsDto;
        }).collect(Collectors.toList());
        return goodsDtos;
    }
}